package com.ea.eadp.nexus.test.common.ApiClients;

import com.ea.eadp.nexus.test.common.*;
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.client.RedirectLocations;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.testng.Assert;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by ChuanYe on 7/24/2014.
 */
public class NexusConnectApi extends NexusApiBase {
    private static NexusConnectApi instance;

    public synchronized static NexusConnectApi instance() {
        if (instance == null) {
            instance = new NexusConnectApi();
        }
        instance.client = NexusHttpClients.getConnectClient();
        return instance;
    }

    private static String client_id = SystemProperties.instance().getProperty(SystemProperties.ClientId);
    private static String secret = SystemProperties.instance().getProperty(SystemProperties.Serect);
    private static String ConnectBaseUri = TestUtil.BaseConnectURI();
    private static String HttpsConnectBaseUri = TestUtil.BaseHttpsConnectURI();
    private static String HttpConnectInternalBaseUri = TestUtil.BaseHttpConnectInternalURI();

    private static String typeMobileUpid = "MOBILE_UPID";
    private static String typeMobileFacebook = "MOBILE_FACEBOOK";
    private static String typeMobileGameCenter = "MOBILE_GAME_CENTER";
    private static String typeMobileOrigin = "NUCLEUS";

    private static String signupPassword = "1234qwER";

    private static String mobileAnonymousAuthenticatorType = "mobile_anonymous";
    private static String mobileFacebookAuthenticatorType = "mobile_facebook";
    private static String mobileEAAuthenticatorType = "mobile_ea_account";
    private static String mobileGameCenterAuthenticatorType = "mobile_game_center";
    private static String mobileGooglePlusAuthenticatorType = "mobile_google_plus";

    private String getCodeUri() {
        return getCodeUri(client_id);
    }

    private String getCodeUri(String client_id) {
        return String.format("%1$s/connect/auth?display=web/login&response_type=code&client_id=%2$s", ConnectBaseUri, client_id);
    }

    private String getTokenUri(String client_id) {
        return String.format("%1$s/connect/auth?display=web/login&response_type=token&client_id=%2$s", ConnectBaseUri, client_id);
    }

    private String getCodeUriForAntelopeAnonymous(String client_id, String sig, String authenticatorType) {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&sig=%3$s&authenticator_login_type=%4$s", ConnectBaseUri, client_id, sig, authenticatorType);
    }

    private String getUriForProgressiveRegistration (String client_id,String access_token,String email, String country,String dob) {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&access_token=%3$s&email=%4$s&country=%5$s&dob=%6$s", ConnectBaseUri, client_id,access_token ,email, country,dob);
    }
    private String getCodeUriForAntelopeLnglv_token(String client_id,String authenticatorType) {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&authenticator_login_type=%3$s", ConnectBaseUri, client_id, authenticatorType);
    }
    private String getCodeUriForAntelopeFacebook(String client_id, String fb_token, String authenticatorType) {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&fb_token=%3$s&authenticator_login_type=%4$s", ConnectBaseUri, client_id, fb_token, authenticatorType);
    }

    private String getCodeUriForAntelopeGameCenter_test(String client_id, String gamecenterId, String authenticatorType) {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&gctest_playerId=%3$s&authenticator_login_type=%4$s", ConnectBaseUri, client_id, gamecenterId, authenticatorType);
    }

       private String getCodeUriForAntelopeGooglePlus_test(String client_id, String googlePlusId, String authenticatorType) {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&gptest_token=%3$s&authenticator_login_type=%4$s", ConnectBaseUri, client_id, googlePlusId, authenticatorType);
    }
    private String getCodeUriForAntelopeEAAccount(String client_id, String sig, String authenticatorType)  {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=code&sig=%3$s&authenticator_login_type=%4$s", ConnectBaseUri, client_id,sig, authenticatorType);
    }
    private String getCodeUriForAntelopeEAAccount(String client_id, String sig, String authenticatorType,String response_type,String nonce)  {
        return String.format("%1$s/connect/auth?client_id=%2$s&response_type=%3$s&sig=%4$s&authenticator_login_type=%5$s&&nonce=%6$s", ConnectBaseUri, client_id,response_type,sig, authenticatorType,nonce);
    }

    private String getCodeUriForMobileAnonymous(String client_id, String deviceId) {
        return String.format("%1$s/connect/auth?mobile_login_type=mobile_game_device_id&response_type=code&client_id=%2$s&mobile_device_id=%3$s", ConnectBaseUri, client_id, deviceId);
    }

    private String getCodeUriForMobileUpidToken(String client_id, String upidToken) {
        return String.format("%1$s/connect/auth?mobile_login_type=mobile_game_UPID&response_type=code&client_id=%2$s&mobile_UPIDToken=%3$s", ConnectBaseUri, client_id, upidToken);
    }

    private String getCodeUriForMobileGameCenterId(String client_id, String gameCenterId) {
        return String.format("%1$s/connect/auth?mobile_login_type=mobile_game_game_center&response_type=code&client_id=%2$s&gc_pid=%3$s", ConnectBaseUri, client_id, gameCenterId);
    }

    private String getCodeUriForMobileFacebook(String client_id, String fbToken) {
        return String.format("%1$s/connect/auth?mobile_login_type=mobile_game_facebook&response_type=code&client_id=%2$s&fb_token=%3$s", ConnectBaseUri, client_id, fbToken);
    }

    private String getUpidTokenUri(String client_id) {
        return String.format("%1$s/connect/upidtoken?client_id=%2$s", ConnectBaseUri, client_id);
    }

    private String getCodeUriForMobileOriginUpgrade(String client_id, String deviceId) {
        return String.format("%1$s/connect/auth?mobile_login_type=mobile_game_origin_upgrade&response_type=code&client_id=%2$s&mobile_device_id=%3$s&display=web/login&redirect_uri=http://localhost", ConnectBaseUri, client_id, deviceId);
    }

    private String getCodeUriForMobileOrigin(String client_id) {
        return String.format("%1$s/connect/auth?mobile_login_type=mobile_game_origin&response_type=code&client_id=%2$s&display=web/login&redirect_uri=http://localhost", ConnectBaseUri, client_id);
    }

    private String postClientInfoUri() {
        return String.format("%1$s/connect/clientinfo", HttpConnectInternalBaseUri);
    }

    public List<TokenInfo> getTokensInfo(List<AccessToken> tokens, String client_id) throws Exception {
        return getTokensInfo(tokens, client_id, ConnectBaseUri, null, null);
    }

    public List<TokenInfo> getTokensInfoInternal(List<AccessToken> tokens, String client_id) throws Exception {
        return getTokensInfo(tokens, client_id, HttpConnectInternalBaseUri, null, null);
    }

    public List<TokenInfo> getTokensInfoWithExtraHeader(List<AccessToken> tokens, String client_id, String header, String value) throws Exception {
        return getTokensInfo(tokens, client_id, ConnectBaseUri, header, value);
    }

    public List<TokenInfo> getTokensInfo(List<AccessToken> tokens, String client_id, String baseUri, String header, String value) throws Exception {
        String accessTokensStr = "";
        for (int i = 0; i < tokens.size(); i++) {
            accessTokensStr += "access_token=" + tokens.get(i).getAccess_token();
            if (i != tokens.size() - 1) {
                accessTokensStr += "&";
            }
        }
        String getUri = baseUri + "/connect/tokensinfo?" + accessTokensStr + "&client_id=" + client_id;

        HttpGet httpGet = new HttpGet(getUri);
        if(header != null && value != null){
            httpGet.addHeader(header, value);
        }
        String tokensInfoString = IOUtils.toString(get(httpGet, null).getEntity().getContent());
        log.info(tokensInfoString);
        try {
            TokensInfo tokensInfo = TestUtil.parseJson(tokensInfoString, TokensInfo.class);
            return tokensInfo.getTokensInfo();
        } catch (UnrecognizedPropertyException ex) {
            log.info(ex.getMessage());
            throw new Exception(tokensInfoString);
        }

    }

    public HttpResponse migrate(String srcAccessToken, String targetAccesstoken, String clientId, String tuid) throws Exception {
        HashMap<String, String> headers = new HashMap<String, String>();
        if (srcAccessToken != null) {
            headers.put("X-SOURCE-ACCESS-TOKEN", srcAccessToken);
        }
        if (targetAccesstoken != null) {
            headers.put("X-TARGET-ACCESS-TOKEN", targetAccesstoken);
        }

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        if (clientId != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", clientId));
        }
        if (tuid != null) {
            nameValuePairs.add(new BasicNameValuePair("tuid", tuid));
        }
        String migrateUri = ConnectBaseUri + "/connect/migrate";
        HttpPost httpPost = new HttpPost(migrateUri);
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);

        //Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
        return response;
    }

    public void unLink(String client_id, String accessToken) throws Exception {
        unLink(client_id, accessToken, null);
    }

    public void unLink(String client_id, String accessToken, String mobileDeviceId) throws Exception {
        String getUri = ConnectBaseUri + "/connect/unlink?" + "client_id=" + client_id + "&access_token=" + accessToken;
        if (mobileDeviceId != null) {
            getUri += "&mobile_device_id=" + mobileDeviceId;
        }

        HttpGet httpGet = new HttpGet(getUri);
        HttpResponse response = get(httpGet, null);

        Assert.assertEquals(200, response.getStatusLine().getStatusCode());
    }

    public TokenInfo getTokenInfo(AccessToken token) throws Exception {
        String getUri = ConnectBaseUri + "/connect/tokeninfo?access_token=" + token.getAccess_token();

        HttpGet httpGet = new HttpGet(getUri);
        String tokenInfoString = IOUtils.toString(get(httpGet, null).getEntity().getContent());
        log.info(tokenInfoString);
        return TestUtil.parseJson(tokenInfoString, TokenInfo.class);
    }

    public TokenInfo getTokenInfoWithOperationMode(AccessToken token, String operationMode) throws Exception {
        HashMap<String, String> hashMap = new HashMap<>();
        if (operationMode != null) hashMap.put("X_QA_REDIS_OPERATION_MODE", operationMode);

        return TestUtil.parseJson(getTokenInfo(token, hashMap), TokenInfo.class);
    }

    public String getTokenInfo(AccessToken token, HashMap<String, String> headers) throws Exception {
        String getUri = ConnectBaseUri + "/connect/tokeninfo?access_token=" + token.getAccess_token();

        HttpGet httpGet = new HttpGet(getUri);
        if (headers != null) {
            for (Map.Entry<String, String> s : headers.entrySet()) {
                httpGet.setHeader(s.getKey(), s.getValue());
            }
        }
        String tokenInfoString = IOUtils.toString(get(httpGet, null).getEntity().getContent());
        log.info(tokenInfoString);
        return tokenInfoString;
    }

    public TokenInfo getTokenInfo(String authToken) throws Exception {
        String getUri = ConnectBaseUri + "/connect/tokeninfo?access_token=" + authToken + "&client_id=" + client_id;

        HttpGet httpGet = new HttpGet(getUri);
        String tokenInfoString = IOUtils.toString(get(httpGet, null).getEntity().getContent());
        log.info(tokenInfoString);
        return TestUtil.parseJson(tokenInfoString, TokenInfo.class);
    }

    public TokenInfo getTokenInfoWithExtraHeader(String authToken,String client_id,HashMap<String, String> headers) throws Exception {
        String getUri = ConnectBaseUri + "/connect/tokeninfo?access_token=" + authToken + "&client_id=" + client_id;

        HttpGet httpGet = new HttpGet(getUri);
        if (headers != null) {
            for (Map.Entry<String, String> s : headers.entrySet()) {
                httpGet.setHeader(s.getKey(), s.getValue());
            }
        }
        String tokenInfoString = IOUtils.toString(get(httpGet, null).getEntity().getContent());
        log.info(tokenInfoString);
        return TestUtil.parseJson(tokenInfoString, TokenInfo.class);
    }

    public String getCodeByToken(AccessToken token) throws Exception {
        return getCodeByToken(token, client_id);
    }

    public String getCodeByTokenToSpecifyUserPersona(AccessToken token, String displayName, String namespaceName) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = getCodeUri(client_id) + "&persona_display_name=" + displayName + "&persona_namespace=" + namespaceName;
        HttpGet httpGet = new HttpGet(oneboxUri);
        httpGet.setHeader("access_token", token.getAccess_token());
        try {
            get(httpGet, httpContext);//client.execute(httpGet, httpContext);
        } catch (Exception e) {

        }
        String currentUrl = TestUtil.getCurrentUrl(httpContext);
        if (!currentUrl.contains("?code=")) {
            throw new Exception("expected code value not found, http response entity: " +
                    IOUtils.toString(((HttpResponse) httpContext.getAttribute(ExecutionContext.HTTP_RESPONSE)).getEntity().getContent()));
        }
        return currentUrl.substring(currentUrl.indexOf("code=") + 5);
    }

    public String getCodeByToken(AccessToken token, String client_id) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = getCodeUri(client_id);
        HttpGet httpGet = new HttpGet(oneboxUri);
        httpGet.setHeader("access_token", token.getAccess_token());
        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new Exception("Wrong response status for getCodeByToken");
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByToken");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;
        } catch (Exception e) {

        }
        String currentUrl = TestUtil.getCurrentUrl(httpContext);
        if (!currentUrl.contains("?code=")) {
            throw new Exception("expected code value not found, http response entity: " +
                    IOUtils.toString(((HttpResponse) httpContext.getAttribute(ExecutionContext.HTTP_RESPONSE)).getEntity().getContent()));
        }
        return currentUrl.substring(currentUrl.indexOf("code=") + 5);
    }

    public String getCodeByXboxToken(String xToken) throws Exception {
        return getCodeByXboxTokenWithClientId(xToken, client_id);
    }

    public String getCodeByXboxTokenWithClientId(String xToken, String client_id) throws Exception {
        String oneboxUri = "%1$s/connect/auth?client_id=%2$s&response_type=code&xtoken=%3$s";
        oneboxUri = String.format(oneboxUri, ConnectBaseUri, client_id, xToken);
        HttpGet httpGet = new HttpGet(oneboxUri);
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new Exception("Wrong response status for getCodeByToken");
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByToken");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        String currentUrl = TestUtil.getCurrentUrl(httpContext);
        if (!currentUrl.contains("?code=")) {
            throw new Exception("expected code value not found, http response entity: " +
                    IOUtils.toString(((HttpResponse) httpContext.getAttribute(ExecutionContext.HTTP_RESPONSE)).getEntity().getContent()));
        }
        return currentUrl.substring(currentUrl.indexOf("code=") + 5);

    }

    public String getCodeByPS3Ticket(String ps3ticket) throws Exception {
        return getCodeByPS3TicketWithClientId(ps3ticket, client_id);
    }

    public String getCodeByPS3TicketWithClientId(String ps3ticket, String client_id) throws Exception {
        String oneboxUri = "%1$s/connect/auth?client_id=%2$s&response_type=code&psn_ticket=%3$s";
        oneboxUri = String.format(oneboxUri, ConnectBaseUri, client_id, ps3ticket);
        HttpGet httpGet = new HttpGet(oneboxUri);
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new Exception("Wrong response status for getCodeByToken");
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByToken");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;
        } catch (Exception e) {

        }
        String currentUrl = TestUtil.getCurrentUrl(httpContext);
        if (!currentUrl.contains("?code=")) {
            throw new Exception("expected code value not found, http response entity: " +
                    IOUtils.toString(((HttpResponse) httpContext.getAttribute(ExecutionContext.HTTP_RESPONSE)).getEntity().getContent()));
        }
        return currentUrl.substring(currentUrl.indexOf("code=") + 5);

    }

    public String getCodeByXboxToken(String signupEmail, String signupPassword) throws Exception {
        HashMap<String, String> map = new HashMap<String, String>(1);
        map.put("xtoken", IOUtils.toString(getClass().getClassLoader().getResourceAsStream("config/xtoken.txt")));
        return getCode(signupEmail, signupPassword, map);
    }

    public String getCodeByPsnTicket(String signupEmail, String signupPassword, String client_id) throws Exception {
        HashMap<String, String> map = new HashMap<String, String>(1);
        map.put("psn_ticket", "MQAAAAAAAPgwAACsAAgAFL+seK4T53OZfeU476cTzMs/pF0hAAEABAAAAAEABwAIAAABPUvdR0QABwAIAAABPUvmbCgAAgAIQrQNxGdMPm8ABAAgUS1rVkZGdG5tbC1VUy1FTgAAAAAAAAAAAAAAAAAAAAAACAAEdXMAAQAEAARhMAAAAAgAGFVQMDAwNi1OUFhYMDAyNDVfMDAAAAAAADARAAQHsgEBAAEABCsAAgAwEAAAAAAAADACAEQACAAEOC3ljQAIADgwNgIZALrCBv9uDjlpK4fv8RgmjCJx7CZd4Q9d+QIZANzsPcRDSZcaNHSr3AtNqI4+pX00Zzcmjw==");
        return getCode(signupEmail, signupPassword, map, client_id, null);
    }

    public String getCodeByPsnTicket(String signupEmail, String signupPassword) throws Exception {
        return getCodeByPsnTicket(signupEmail, signupPassword, client_id);
    }

    public String getCodeByPsnTicket(String signupEmail, String signupPassword, String client_id, String psnTicket) throws Exception {
        HashMap<String, String> map = new HashMap<String, String>(1);
        map.put("psn_ticket", psnTicket);
        return getCode(signupEmail, signupPassword, map, client_id, null);
    }

    public String getCode(String signupEmail, String signupPassword, String scope) throws Exception {
        return getCode(signupEmail, signupPassword, new HashMap<String, String>(0), client_id, scope);
    }

    public String getCode(String signupEmail, String signupPassword) throws Exception {
        return getCode(signupEmail, signupPassword, new HashMap<String, String>(0));
    }

    public String getLegacyCode(String signupEmail, String signupPassword) throws Exception {
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("X_QA_REDIS_OPERATION_MODE", "RAW_READ_WRITE");
        map.put("X_QA_AUTH_CODE_VERSION", "1.0");
        return getCode(signupEmail, signupPassword, map);
    }

    public String getCode(String signupEmail, String signupPassword, Map<String, String> headers) throws Exception {
        return getCode(signupEmail, signupPassword, headers, client_id, "");
    }

    public String getCode(String signupEmail, String signupPassword, Map<String, String> headers, String client_id, String scope) throws Exception {
        return getCode(signupEmail, signupPassword, headers, client_id, scope, "");
    }

    public String getCode(String signupEmail, String signupPassword, Map<String, String> headers, String client_id, String scope, String redirect_uri) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        String oneboxUri = getCodeUri(client_id);
        if (StringUtils.isNotBlank(redirect_uri)) {
            oneboxUri += "&redirect_uri=" + redirect_uri;
        }

        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        HttpGet httpGet = new HttpGet(oneboxUri);
        if (headers != null) {
            for (Map.Entry<String, String> s : headers.entrySet()) {
                httpGet.setHeader(s.getKey(), s.getValue());
            }
        }

        try {
            get(httpGet, httpContext);
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

        //post user & pwd to login
        try {
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (!currentUrl.contains("login?execution=")) {
                //String message = IOUtils.toString(((HttpResponse)httpContext.getAttribute("http.response")).getEntity().getContent());
                throw new Exception(IOUtils.toString(((HttpResponse) httpContext.getAttribute("http.response")).getEntity().getContent()));
            }
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
            nameValuePairs.add(new BasicNameValuePair("email", signupEmail));
            nameValuePairs.add(new BasicNameValuePair("password", signupPassword));
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            client.setRedirectStrategy(new LaxRedirectStrategy());
            client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user verified email(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return url.substring(url.indexOf("code=") + 5);
            } else {
                RedirectLocations redirectLocations = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations"));
                if (redirectLocations != null) {
                    List<URI> uris = redirectLocations.getAll();
                    url = uris.get(uris.size() - 1).toASCIIString();
                    if (url.contains("?code=")) {
                        return url.substring(url.indexOf("code=") + 5);
                    }
                }
                throw e;
            }
        }
        //confirm login if user's email not verified
        try {
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            client.setRedirectStrategy(new LaxRedirectStrategy());
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user without email verified confirm to login(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw new Exception("expected code value not found");
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return url.substring(url.indexOf("code=") + 5);
            } else {
                List<URI> uris = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations")).getAll();
                url = uris.get(uris.size() - 1).toASCIIString();
                if (url.contains("?code=")) {
                    return url.substring(url.indexOf("code=") + 5);
                }
                throw e;
            }
        }
    }


    /*
    public static String getTokenStr(String signupEmail, String signupPassword, Map<String, String> headers, String client_id, String scope, String redirect_uri, String expiresIn) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = getTokenUri(client_id);
        if (StringUtils.isNotBlank(redirect_uri)){
            oneboxUri += "&redirect_uri=" + redirect_uri;
        }
        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        if (StringUtils.isNotBlank(expiresIn)){
            oneboxUri += "&expires_in=" + expiresIn;
        }
        HttpGet httpGet = new HttpGet(oneboxUri);
        if (headers != null) {
            for (Map.Entry<String, String> s : headers.entrySet()) {
                httpGet.setHeader(s.getKey(), s.getValue());
            }
        }

        try {
            get(httpGet, httpContext);
            String currentUrl =TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("access_token=")) {
                //return code(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("expires_in="));
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl =TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("access_token=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("expires_in="));
            } else {
                throw e;
            }
        }

        //post user & pwd to login
        try {
            String currentUrl =TestUtil.getCurrentUrl(httpContext);
            if (!currentUrl.contains("login?execution=")) {
                //String message = IOUtils.toString(((HttpResponse)httpContext.getAttribute("http.response")).getEntity().getContent());
                throw new Exception(IOUtils.toString(((HttpResponse) httpContext.getAttribute("http.response")).getEntity().getContent()));
            }
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
            nameValuePairs.add(new BasicNameValuePair("email", signupEmail));
            nameValuePairs.add(new BasicNameValuePair("password", signupPassword));
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            client.setRedirectStrategy(new LaxRedirectStrategy());
            client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl =TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("access_token=")) {
                //return code if user verified email(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("expires_in="));
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url =TestUtil.getCurrentUrl(httpContext);
            if (url.contains("access_token=")) {
                return url.substring(url.indexOf("expires_in="));
            } else {
                RedirectLocations redirectLocations = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations"));
                if (redirectLocations != null) {
                    List<URI> uris = redirectLocations.getAll();
                    url = uris.get(uris.size() - 1).toASCIIString();
                    if (url.contains("access_token=")) {
                        return url.substring(url.indexOf("expires_in="));
                    }
                }
                throw e;
            }
        }
        //confirm login if user's email not verified
        try {
            String currentUrl =TestUtil.getCurrentUrl(httpContext);
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            client.setRedirectStrategy(new LaxRedirectStrategy());
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl =TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("access_token=")) {
                //return code if user without email verified confirm to login(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("expires_in="));
            } else {
                throw new Exception("expected access_token value not found");
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url =TestUtil.getCurrentUrl(httpContext);
            if (url.contains("access_token=")) {
                return url.substring(url.indexOf("expires_in="));
            } else {
                List<URI> uris = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations")).getAll();
                url = uris.get(uris.size() - 1).toASCIIString();
                if (url.contains("access_token=")) {
                    return url.substring(url.indexOf("expires_in="));
                }
                throw e;
            }
        }
    }*/

    public String getCodeByMobileUpidTokenWithIp(String upidToken, String clientId, String scope, String ipAddress) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        CookieStore cookieStore = new BasicCookieStore();
        String oneboxUri = getCodeUriForMobileUpidToken(clientId, upidToken);
        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        HttpGet httpGet = new HttpGet(oneboxUri);
        httpGet.addHeader("x-forwarded-for", ipAddress);
        httpGet.addHeader("Nucleus-RequestorId", "Nexus");
        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new Exception("Wrong response status for getCodeByMobileUpidToken");
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByMobileUpidToken");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

    }

    public String getCodeByAntelopeAnonymous(String clientId, String sig, String loginType) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeAnonymous(clientId, sig,loginType);
        HttpGet httpGet = new HttpGet(uri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByAntelopeAnonymous" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByAntelopeAnonymous");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByAntelopeAnonymous(String clientId, String sig) throws Exception {
        return getCodeByAntelopeAnonymous(clientId, sig, mobileAnonymousAuthenticatorType);
    }

    public String getCodeByAntelopeEAAccount(String clientId, String sig, String loginType,String response_type ) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeEAAccount(clientId, sig,loginType,response_type,String.valueOf(System.currentTimeMillis()));
        HttpGet httpGet = new HttpGet(uri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByAntelopeEAAccount" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByAntelopeEAAccount");
            }
           return responseMessage;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }


    public String getCodeByAntelopeEAAccount(String clientId, String sig, String loginType) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeEAAccount(clientId, sig, loginType);
        HttpGet httpGet = new HttpGet(uri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByAntelopeEAAccount" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByAntelopeEAAccount");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByAntelopeEAAccount(String clientId, String sig) throws Exception {
        return getCodeByAntelopeEAAccount(clientId, sig, mobileEAAuthenticatorType);
    }
    public String getCodeLnglv_tokenByAntelopeEAAccount(String clientId, String sig) throws Exception {
        return getCodeByAntelopeEAAccount(clientId, sig,mobileEAAuthenticatorType,"code+lnglv_token");
    }
    public String getCodeByAntelopeLnglv_token(String lnglv_token,String clientId, String loginType) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeLnglv_token(clientId,loginType);
        HttpGet httpGet = new HttpGet(uri);
        if (lnglv_token!=null){
            httpGet.addHeader("lnglv_token",lnglv_token);
        }

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200 || EntityUtils.toString(response.getEntity(), "UTF-8").contains("error_code")) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByAntelopeLnglv_token" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByAntelopeLnglv_token");
            }

            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByAntelopeFacebook(String clientId, String fb_token, String loginType) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeFacebook(clientId, fb_token, loginType);
        HttpGet httpGet = new HttpGet(uri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByMobileFacebook" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByMobileFacebook");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByAntelopeFacebook(String clientId, String fb_token) throws Exception {
        return getCodeByAntelopeFacebook(clientId, fb_token, mobileFacebookAuthenticatorType);
    }

    public String getCodeByAntelopeGameCenter_test(String clientId, String gcPid, String loginType) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeGameCenter_test(clientId, gcPid, loginType);
        HttpGet httpGet = new HttpGet(uri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByAntelopeGameCenter_test" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByAntelopeGameCenter_test");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByAntelopeGameCenter_test(String clientId, String gcPid) throws Exception {
        return getCodeByAntelopeGameCenter_test(clientId, gcPid, mobileGameCenterAuthenticatorType);
    }

    public String getCodeByAntelopeGooglePlus_test(String clientId, String googlePlusId, String loginType) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        String uri = getCodeUriForAntelopeGooglePlus_test(clientId, googlePlusId, loginType);
        HttpGet httpGet = new HttpGet(uri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByAntelopeGooglePlus_test" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByAntelopeGooglePlus_test");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByAntelopeGooglePlus_test(String clientId, String googlePlusId) throws Exception {
        return getCodeByAntelopeGooglePlus_test(clientId, googlePlusId, mobileGooglePlusAuthenticatorType);
    }

    public AccessToken addAuthenticator(String previous_access_token, String code, String transaction_guid, String client_id, String client_secret, String link_persona_id) throws Exception {
        return addAuthenticator(previous_access_token, code, transaction_guid, client_id, client_secret, link_persona_id, null);
    }
    public AccessToken addAuthenticator(String previous_access_token, String code, String transaction_guid, String client_id, String client_secret, String link_persona_id, HashMap<String, String> headers) throws Exception {
        if (headers==null){
            headers = new HashMap<String,String>();
        }
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(6);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "add_authenticator"));
        if (previous_access_token != null) {
            nameValuePairs.add(new BasicNameValuePair("previous_access_token", previous_access_token));
        }
        if (code != null) {
            nameValuePairs.add(new BasicNameValuePair("code", code));
        }
        if (transaction_guid != null) {
            nameValuePairs.add(new BasicNameValuePair("transaction_guid", transaction_guid));
        }
        if (client_id != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        }
        if (client_secret != null) {
            nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret));
        }
        if (link_persona_id != null) {
            headers.put("X-Link-Persona-Id", link_persona_id);
        }
        HttpResponse response = getTokenResponse(client, nameValuePairs, headers, ConnectBaseUri);
        int statusCode = response.getStatusLine().getStatusCode();
        String statusReason = response.getStatusLine().getReasonPhrase();
        String tokenString = IOUtils.toString(response.getEntity().getContent());

        if(statusCode == 300) {
            Assert.assertEquals(statusReason,"Multiple Choices");
        }

        log.info(tokenString);
        try {
            return TestUtil.parseJson(tokenString, AccessToken.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(response.getStatusLine().getStatusCode() + " " + tokenString);
        }
    }
    public AccessToken switchGameState (String access_token, String transaction_guid,String client_id, String client_secret, String persona_id) throws Exception {
        return switchAuthenticator(access_token, transaction_guid,client_id, client_secret,persona_id,  null);
    }

    public AccessToken switchAuthenticator(String access_token , String transaction_guid,String client_id, String client_secret,  String persona_id, HashMap<String, String> headers) throws Exception {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("grant_type", "change_game_state"));
        if (access_token != null) {
            nameValuePairs.add(new BasicNameValuePair("access_token", access_token));
        }

        if (transaction_guid != null) {
            nameValuePairs.add(new BasicNameValuePair("transaction_guid", transaction_guid));
        }
        if (client_id != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        }
        if (client_secret != null) {
            nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret));
        }
        if (persona_id != null) {
            nameValuePairs.add(new BasicNameValuePair("persona_id", persona_id));
        }
        HttpResponse response = getTokenResponse(client, nameValuePairs, headers, ConnectBaseUri);
        int statusCode = response.getStatusLine().getStatusCode();
        String statusReason = response.getStatusLine().getReasonPhrase();
        String tokenString = IOUtils.toString(response.getEntity().getContent());

        if(statusCode == 300) {
            Assert.assertEquals(statusReason,"Multiple Choices");
        }

        log.info(tokenString);
        try {
            return TestUtil.parseJson(tokenString, AccessToken.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(response.getStatusLine().getStatusCode() + " " + tokenString);
        }
    }

    public AccessToken removeAuthenticator(String access_token,String transaction_guid, String client_id, String client_secret, String authenticatorType) throws Exception {
        return removeAuthenticatorWithHeaders(access_token,transaction_guid, client_id, client_secret, authenticatorType,null);
    }
    public AccessToken removeAuthenticatorWithLnglv_token(String access_token,String transaction_guid, String client_id, String client_secret, String authenticatorType,String lnglv_token) throws Exception {
        HashMap<String, String> headers = new HashMap<String, String>();
        if (lnglv_token!=null){
            headers.put("lnglv_token",lnglv_token);
        }
        if (headers.size()>0){
            return removeAuthenticatorWithHeaders(access_token,transaction_guid, client_id, client_secret, authenticatorType,headers);
        }
        return removeAuthenticatorWithHeaders(access_token,transaction_guid, client_id, client_secret, authenticatorType,null);
    }
    public AccessToken removeAuthenticatorWithHeaders(String access_token,String transaction_guid, String client_id, String client_secret, String authenticatorType, HashMap<String, String> headers) throws Exception {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(6);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "remove_authenticator"));
        if (access_token != null) {
            nameValuePairs.add(new BasicNameValuePair("access_token", access_token));
        }
        if (authenticatorType != null) {
            nameValuePairs.add(new BasicNameValuePair("authenticator_type", authenticatorType));
        }
        if (transaction_guid != null) {
            nameValuePairs.add(new BasicNameValuePair("transaction_guid", transaction_guid));
        }
        if (client_id != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        }
        if (client_secret != null) {
            nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret));
        }

        return getToken(client, nameValuePairs, headers, ConnectBaseUri);
    }

    public String getCodeByMobileUpidToken(String upidToken, String clientId, String scope) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        CookieStore cookieStore = new BasicCookieStore();
        String oneboxUri = getCodeUriForMobileUpidToken(clientId, upidToken);
        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        HttpGet httpGet = new HttpGet(oneboxUri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new Exception("Wrong response status for getCodeByMobileUpidToken");
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByMobileUpidToken");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

    }

    public String getCodeByMobileGameCenterIdAndName(String gcId, String gcName, String clientId, String scope) throws Exception {
        return getCodeByMobileGameCenterIdAndNameWithValidation(gcId, gcName, clientId, scope, null, null, null, null, null);

    }

    public String getCodeByMobileGameCenterIdAndNameWithValidation(String gcId, String gcName, String clientId, String scope, String publicKeyUrl, String signature, String bundleId, String timeStamp, String salt) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        CookieStore cookieStore = new BasicCookieStore();
        String oneboxUri;
        oneboxUri = getCodeUriForMobileGameCenterId(clientId, gcId);

        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        if (gcName != null) {
            oneboxUri = oneboxUri.concat("&gc_pname=" + gcName);
        }
        if (publicKeyUrl != null) {
            oneboxUri = oneboxUri.concat("&public_key_url=" + publicKeyUrl);
        }
        if (signature != null) {
            oneboxUri = oneboxUri.concat("&signature=" + signature);
        }
        if (bundleId != null) {
            oneboxUri = oneboxUri.concat("&bundle_id=" + bundleId);
        }
        if (timeStamp != null) {
            oneboxUri = oneboxUri.concat("&timestamp=" + timeStamp);
        }
        if (salt != null) {
            oneboxUri = oneboxUri.concat("&salt=" + salt);
        }
        HttpGet httpGet = new HttpGet(oneboxUri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByMobileGameCenterIdAndNameWithValidation" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByMobileGameCenterIdAndName");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

    }

    public String getCodeByMobileGameCenterId(String gcId, String clientId, String scope) throws Exception {
        return getCodeByMobileGameCenterIdAndName(gcId, null, clientId, scope);
    }

    public String getCodeByMobileFacebook(String fbToken, String clientId, String scope) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        CookieStore cookieStore = new BasicCookieStore();
        String oneboxUri = getCodeUriForMobileFacebook(clientId, fbToken);
        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        HttpGet httpGet = new HttpGet(oneboxUri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                String responseMessage = "";
                if (response.getEntity() != null) {
                    responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
                throw new Exception("Wrong response status for getCodeByMobileFacebook" + responseMessage);
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByMobileFacebook");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }
    }

    public String getCodeByMobileDeviceId(String deviceId, String clientId, String scope) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        CookieStore cookieStore = new BasicCookieStore();
        String oneboxUri = getCodeUriForMobileAnonymous(clientId, deviceId);
        if (scope != null) {
            if (!scope.isEmpty()) {
                oneboxUri = oneboxUri.concat("&scope=" + scope);
            }
        }
        HttpGet httpGet = new HttpGet(oneboxUri);

        try {
            HttpResponse response = get(httpGet, httpContext);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new Exception("Wrong response status for getCodeByMobileDeviceId");
            }

            String responseMessage = null;

            if (response.getEntity() != null) {
                responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
            }

            if (responseMessage == null) {
                throw new Exception("Null response returned for getCodeByMobileDeviceId");
            }
            String code = TestUtil.parseJson(responseMessage).get("code");
            return code;

        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

    }

    public String getCodeByMobileOrigin(String signupEmail, String signupPassword, String client_id) throws Exception {
        return getCodeByMobileOrigin(signupEmail, signupPassword, client_id, null, false);
    }

    public String getCodeByMobileOrigin(String signupEmail, String signupPassword, String client_id, String deviceId, boolean upgrade) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = null;
        if (upgrade == true)
            oneboxUri = getCodeUriForMobileOriginUpgrade(client_id, deviceId);
        else
            oneboxUri = getCodeUriForMobileOrigin(client_id);

        HttpGet httpGet = new HttpGet(oneboxUri);

        try {
            get(httpGet, httpContext);
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

        //post user & pwd to login
        try {
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (!currentUrl.contains("login?execution=")) {
                //String message = IOUtils.toString(((HttpResponse)httpContext.getAttribute("http.response")).getEntity().getContent());
                throw new Exception(IOUtils.toString(((HttpResponse) httpContext.getAttribute("http.response")).getEntity().getContent()));
            }
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
            nameValuePairs.add(new BasicNameValuePair("email", signupEmail));
            nameValuePairs.add(new BasicNameValuePair("password", signupPassword));
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            client.setRedirectStrategy(new LaxRedirectStrategy());
            client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user verified email(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return url.substring(url.indexOf("code=") + 5);
            } else {
                RedirectLocations redirectLocations = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations"));
                if (redirectLocations != null) {
                    List<URI> uris = redirectLocations.getAll();
                    url = uris.get(uris.size() - 1).toASCIIString();
                    if (url.contains("?code=")) {
                        return url.substring(url.indexOf("code=") + 5);
                    }
                }
                throw e;
            }
        }
        //confirm login if user's email not verified
        try {
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            client.setRedirectStrategy(new LaxRedirectStrategy());
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user without email verified confirm to login(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw new Exception("expected code value not found");
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return url.substring(url.indexOf("code=") + 5);
            } else {
                List<URI> uris = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations")).getAll();
                url = uris.get(uris.size() - 1).toASCIIString();
                if (url.contains("?code=")) {
                    return url.substring(url.indexOf("code=") + 5);
                }
                throw e;
            }
        }
    }

    public String getCodeByConsoleClient(String signupEmail, String signupPassword, Map<String, String> headers, String client_id, String scope) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = TestUtil.getConsoleConnectUrl(client_id, scope);
        HttpGet httpGet = new HttpGet(oneboxUri);
        if (headers != null) {
            for (Map.Entry<String, String> s : headers.entrySet()) {
                httpGet.setHeader(s.getKey(), s.getValue());
            }
        }
        HttpResponse response;
        String body;
        try {
            response = get(httpGet, httpContext);
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw e;
            }
        }

        //post user & pwd to login
        try {
            body = IOUtils.toString(response.getEntity().getContent());
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (!currentUrl.contains("welcome?execution=")) {
                //String message = IOUtils.toString(((HttpResponse)httpContext.getAttribute("http.response")).getEntity().getContent());
                throw new Exception(body);
            }
            Pattern regex = Pattern.compile("link=\"\\.(/login\\?fid=.*)\"");
            Matcher regexMatcher = regex.matcher(body);
            if (!regexMatcher.find()) {
                throw new Exception(body);
            }
            String nextUrl = regexMatcher.group(1);
            String currentHost = TestUtil.getCurrentHost(httpContext);
            httpGet = new HttpGet(currentHost + "/p/console" + nextUrl + "&country=US&dob=1999-1-1&language=en");

            response = get(httpGet, httpContext);
            body = IOUtils.toString(response.getEntity().getContent());
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (!currentUrl.contains("login?execution=")) {
                //String message = IOUtils.toString(((HttpResponse)httpContext.getAttribute("http.response")).getEntity().getContent());
                throw new Exception(body);
            }
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
            nameValuePairs.add(new BasicNameValuePair("emailOrOrigin", signupEmail));
            nameValuePairs.add(new BasicNameValuePair("password", signupPassword));
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            client.setRedirectStrategy(new LaxRedirectStrategy());
            client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
            response = post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            body = IOUtils.toString(response.getEntity().getContent());
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user verified email(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return url.substring(url.indexOf("code=") + 5);
            } else {
                RedirectLocations redirectLocations = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations"));
                if (redirectLocations != null) {
                    List<URI> uris = redirectLocations.getAll();
                    url = uris.get(uris.size() - 1).toASCIIString();
                    if (url.contains("?code=")) {
                        return url.substring(url.indexOf("code=") + 5);
                    }
                }
                throw e;
            }
        }
        //confirm login if user hasn't accept the tos
        try {
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            httpGet = new HttpGet(currentUrl + "&_eventId=accept");

            get(httpGet, httpContext);//client.execute(httpPost, httpContext);
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user without email verified confirm to login(redirect successfully)
                return currentUrl.substring(currentUrl.indexOf("code=") + 5);
            } else {
                throw new Exception("expected code value not found");
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return url.substring(url.indexOf("code=") + 5);
            } else {
                List<URI> uris = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations")).getAll();
                url = uris.get(uris.size() - 1).toASCIIString();
                if (url.contains("?code=")) {
                    return url.substring(url.indexOf("code=") + 5);
                }
                throw e;
            }
        }
    }

    public AccessToken getTokenWithCert(String keystore, String client_id) throws Exception {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "client_credentials"));
        if (client_id != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        }
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(HttpsConnectBaseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        //the only exception passing an external httpclient, will update later.
        HttpResponse response = post(httpPost, httpContext, keystore);// client.execute(httpPost, httpContext);
        String tokenString = IOUtils.toString(response.getEntity().getContent());
        log.info(tokenString);
        try {
            return TestUtil.parseJson(tokenString, AccessToken.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(tokenString);
        }
    }

    public AccessToken getTokenWithCertHeader(HashMap<String, String> headers, String client_id) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "client_credentials"));
        if (client_id != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        }
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(ConnectBaseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);
        String tokenString = IOUtils.toString(response.getEntity().getContent());
        log.info(tokenString);
        try {
            return TestUtil.parseJson(tokenString, AccessToken.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(tokenString);
        }
    }

    public AccessToken getTokenWithClientSecret() throws Exception {
        return getTokenWithClientSecret(client_id, secret);
    }

    public AccessToken getTokenWithClientSecret(String client_id, String secret) throws Exception {
        return getTokenWithClientSecret(client_id, secret, false);
    }

    public AccessToken getTokenWithClientSecret(String client_id, String secret, boolean markMigration) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "client_credentials"));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));
        HashMap<String, String> headers = new HashMap<String, String>();
        if (markMigration == true) {
            headers.put("X-Mark-Migration", "true");
        }
        return getToken(client, nameValuePairs, headers);
    }

    public AccessToken getLegacyTokenWithClientSecret() throws Exception {
        return getLegacyTokenWithClientSecret(client_id, secret);
    }

    public AccessToken getLegacyTokenWithClientSecret(String client_id, String secret) throws Exception {
        return getLegacyTokenWithClientSecret(client_id, secret, null);
    }

    public AccessToken getLegacyTokenWithClientSecret(String client_id, String secret, String scope) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "client_credentials"));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));

        if (null != scope) {
            nameValuePairs.add(new BasicNameValuePair("scope", scope));
        }

        HashMap<String, String> headers = new HashMap<String, String>();
        headers.put("X_QA_REDIS_OPERATION_MODE", "RAW_READ_WRITE");
        headers.put("X_QA_ACCESS_TOKEN_VERSION", "2.0");
        headers.put("X_QA_REFRESH_TOKEN_VERSION", "2.0");
        return getToken(client, nameValuePairs, headers);
    }

    public AccessToken getTokenByCodeWithClientSecret(String code) throws Exception {
        return getTokenByCodeWithClientSecret(code, client_id, secret);
    }

    public AccessToken getTokenByCodeWithClientSecretAndLinkAccessTokenAndForceLink(String code, String client_id, String secret, String linkAccessToken, boolean xForceLink) throws Exception {
        return getTokenWithClientSecretAndRedirectUri("authorization_code", code, null, null, null, client_id, secret, null, false, ConnectBaseUri, null, null, linkAccessToken, xForceLink);
    }

    public AccessToken getTokenByCodeWithClientSecretAndRedirectUri(String code, String client_id, String secret, String redirectUri) throws Exception {
        return getTokenByCodeWithClientSecretAndRedirectUri(code, client_id, secret, redirectUri, false, null);
    }

    public AccessToken getTokenWithClientSecretAndRedirectUri(String grantType, String code, String pidId, String accessToken, String refreshToken, String client_id, String secret, String redirectUri, boolean markMigration, String migrationStatus) throws Exception {
        return getTokenWithClientSecretAndRedirectUri(grantType, code, pidId, accessToken, refreshToken, client_id, secret, redirectUri, markMigration, ConnectBaseUri, null, migrationStatus, null, false);
    }

    public AccessToken getTokenWithClientSecretAndRedirectUriInternal(String grantType, String code, String pidId, String accessToken, String refreshToken, String client_id, String secret, String redirectUri, boolean markMigration) throws Exception {
        return getTokenWithClientSecretAndRedirectUri(grantType, code, pidId, accessToken, refreshToken, client_id, secret, redirectUri, markMigration, HttpConnectInternalBaseUri, null, null, null, false);
    }

    public AccessToken getTokenWithClientSecretAndRedirectUri(String grantType, String code, String pidId, String accessToken, String refreshToken, String client_id, String secret, String redirectUri, boolean markMigration, String baseUri, String expiresIn, String migrationStatus) throws Exception {
        return getTokenWithClientSecretAndRedirectUri(grantType, code, pidId, accessToken, refreshToken, client_id, secret, redirectUri, markMigration, baseUri, expiresIn, migrationStatus, null, false);
    }

    public AccessToken getTokenWithClientSecretAndRedirectUri(String grantType, String code, String pidId, String accessToken, String refreshToken, String client_id, String secret, String redirectUri, boolean markMigration, String baseUri, String expiresIn, String migrationStatus, String linkAccessToken, boolean xForceLink) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        if (grantType != null) {
            nameValuePairs.add(new BasicNameValuePair("grant_type", grantType));
        }
        if (code != null) {
            nameValuePairs.add(new BasicNameValuePair("code", code));
        }
        if (pidId != null) {
            nameValuePairs.add(new BasicNameValuePair("pidId", pidId));
        }
        if (accessToken != null) {
            nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));
        }
        if (refreshToken != null) {
            nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
        }
        if (client_id != null) {
            nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        }
        if (secret != null) {
            nameValuePairs.add(new BasicNameValuePair("client_secret", secret));
        }
        if (redirectUri != null)
            nameValuePairs.add(new BasicNameValuePair("redirect_uri", redirectUri));
        if (expiresIn != null)
            nameValuePairs.add(new BasicNameValuePair("expires_in", expiresIn));
        if (linkAccessToken != null)
            nameValuePairs.add(new BasicNameValuePair("link_access_token", linkAccessToken));
        HashMap<String, String> headers = new HashMap<String, String>();
        if (markMigration == true) {
            headers.put("X-Mark-Migration", "true");
        }
        if (migrationStatus != null) {
            headers.put("X-Mark-Migration-Status", migrationStatus);
        }
        if (xForceLink == true) {
            headers.put("X-Force-Link", "true");
        }
        return getToken(client, nameValuePairs, headers, baseUri);
    }

    public AccessToken getTokenByCodeWithClientSecretAndRedirectUri(String code, String client_id, String secret, String redirectUri, boolean markMigration, String migrationStatus) throws Exception {
        return getTokenWithClientSecretAndRedirectUri("authorization_code", code, null, null, null, client_id, secret, redirectUri, markMigration, migrationStatus);
    }

    public AccessToken getTokenByCodeWithClientSecretAndRedirectUriInternal(String code, String client_id, String secret, String redirectUri, boolean markMigration, String migrationStatus) throws Exception {
        return getTokenWithClientSecretAndRedirectUriInternal("authorization_code", code, null, null, null, client_id, secret, redirectUri, markMigration);
    }

    public AccessToken getTokenByCodeWithClientSecret(String code, String client_id, String secret) throws Exception {
        return getTokenByCodeWithClientSecretAndRedirectUri(code, client_id, secret, null);
    }
    public AccessToken getTokenByCodeWithClientSecret(String code, String client_id, String secret,String redirectUri) throws Exception {
        return getTokenByCodeWithClientSecretAndRedirectUri(code, client_id, secret, redirectUri);
    }
    public void postTwoPhaseRegistUser(String client_id, String access_token, String email, String dob, String country) throws Exception{
        HttpPost post = new HttpPost(ConnectBaseUri + "/connect/twophaseregist");
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("access_token", access_token));
        nameValuePairs.add(new BasicNameValuePair("email", email));
        nameValuePairs.add(new BasicNameValuePair("dob", dob));
        nameValuePairs.add(new BasicNameValuePair("country", country));
        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = post(post, null);
        if (response.getStatusLine().getStatusCode() == 200){
            return;
        }
        else if (response.getStatusLine().getStatusCode() == 400){
            throw new Exception(IOUtils.toString(response.getEntity().getContent()));
        }
        else if (response.getStatusLine().getStatusCode() == 409) {
            throw new Exception(IOUtils.toString(response.getEntity().getContent()));
        }
        else {
            throw new Exception("not expected error.");
        }
    }
    public String postProgressiveRegistUser(String client_id, String access_token, String email, String country, String dob,String language,String platform,boolean prog_reg) throws Exception{
        return postProgressiveRegistUser(client_id, access_token, email, country, dob, language, platform, prog_reg,null);
    }
    public String postMobileNativeLogin(String client_id, String sig) throws Exception {
        HttpPost post = new HttpPost(ConnectBaseUri + "/connect/auth");
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("response_type", "code"));
        nameValuePairs.add(new BasicNameValuePair("sig", sig));
        nameValuePairs.add(new BasicNameValuePair("redirect_uri", "nucleus:rest"));
        post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = post(post, null);
        if (response.getStatusLine().getStatusCode() == 200){
            return IOUtils.toString(response.getEntity().getContent());
        }
        else {
            throw new Exception(IOUtils.toString(response.getEntity().getContent()));
        }
    }

    public String postProgressiveRegistUser(String client_id, String access_token, String email, String country, String dob,String language,String platform,boolean prog_reg, String ipAddress) throws Exception{
        HttpContext httpContext = new BasicHttpContext();
        CookieStore cookieStore = new BasicCookieStore();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        String oneboxUri = getUriForProgressiveRegistration(client_id,access_token,email,country,dob);
        if (language!=null){
            oneboxUri+="&language="+language;
        }
        if (platform!=null){
            oneboxUri+="&platform="+platform;
        }
        if (prog_reg){
            oneboxUri+="&prog_reg="+prog_reg;
        }
        HttpGet httpGet = new HttpGet(oneboxUri);
        if(ipAddress!=null)
            httpGet.addHeader("x-forwarded-for", ipAddress);
        HttpResponse response = get(httpGet, httpContext);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new Exception(EntityUtils.toString(response.getEntity(), "UTF-8"));
        }

        String responseMessage = null;

        if (response.getEntity() != null) {
            responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
        }

        if (responseMessage == null) {
            throw new Exception("Null response returned for Progressive registration");
        }
        return responseMessage;
    }

    public AccessToken getTokenByCodeWithCert(String keyStore, String client_id, String code) throws Exception {
        HttpsClient client = NexusHttpClients.getHttpsClient(keyStore);
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
        nameValuePairs.add(new BasicNameValuePair("code", code));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        return getToken(client, nameValuePairs, null);
    }

    public AccessToken getTokenByUserPwdWithClientSecret(String user, String pwd) throws Exception {
        return getTokenByUserPwdWithClientSecret(user, pwd, client_id, secret, null, null);
    }

    public AccessToken getTokenByUserPwdWithClientSecret(String user, String pwd, HashMap<String, String> headers) throws Exception {
        return getTokenByUserPwdWithClientSecret(user, pwd, client_id, secret, headers, null);
    }

    public AccessToken getTokenByUserPwdWithClientSecret(String user, String pwd, String client_id, String secret, HashMap<String, String> headers) throws Exception {
        return getTokenByUserPwdWithClientSecret(user, pwd, client_id, secret, headers, null);
    }

    public AccessToken getTokenByUserPwdWithClientSecret(String user, String pwd, String client_id, String secret, HashMap<String, String> headers, String expiresIn) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "password"));
        nameValuePairs.add(new BasicNameValuePair("username", user));
        nameValuePairs.add(new BasicNameValuePair("password", pwd));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));
        if (expiresIn != null) {
            nameValuePairs.add(new BasicNameValuePair("expires_in", expiresIn));
        }

        return getToken(client, nameValuePairs, headers);
    }

    public HttpResponse accessGetCodeUri(Map<String, String> headers) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        String oneboxUri = getCodeUri(client_id);

        HttpGet httpGet = new HttpGet(oneboxUri);
        if (headers != null) {
            for (Map.Entry<String, String> s : headers.entrySet()) {
                httpGet.setHeader(s.getKey(), s.getValue());
            }
        }
        HttpResponse response = get(httpGet, httpContext);
        return response;
    }

    private AccessToken getToken(DefaultHttpClient client, List<NameValuePair> nameValuePairs, HashMap<String, String> headers) throws Exception {
        return getToken(client, nameValuePairs, headers, ConnectBaseUri);
    }

    private AccessToken getToken(DefaultHttpClient client, List<NameValuePair> nameValuePairs, HashMap<String, String> headers, String baseUri) throws Exception {
        HttpResponse response = getTokenResponse(client, nameValuePairs, headers, baseUri);
        String tokenString = IOUtils.toString(response.getEntity().getContent());
        log.info(tokenString);
        try {
            return TestUtil.parseJson(tokenString, AccessToken.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(response.getStatusLine().getStatusCode() + " " + tokenString);
        }
    }

    private HttpResponse getTokenResponse(DefaultHttpClient client, List<NameValuePair> nameValuePairs, HashMap<String, String> headers, String baseUri) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(baseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);
        return response;
    }

    public AccessToken refreshToken(String client_id, String secret, AccessToken token) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));
        nameValuePairs.add(new BasicNameValuePair("refresh_token", token.getRefresh_token()));
        return getToken(client, nameValuePairs, null);
    }

    public AccessToken refreshTokenWithOperationMode(String client_id, String secret, AccessToken token, String operationMode) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));
        nameValuePairs.add(new BasicNameValuePair("refresh_token", token.getRefresh_token()));

        HashMap<String, String> headers = new HashMap<>();
        headers.put("X_QA_REDIS_OPERATION_MODE", operationMode);
        return getToken(client, nameValuePairs, headers);
    }

    public AccessToken refreshToken(AccessToken token) throws Exception {
        return refreshToken(client_id, secret, token);
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByCodeWithClientSecret(String code, String client_id, String secret) throws Exception {
        return getClientMigrationRecordByCodeWithClientSecret(code, client_id, secret, false);
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByCodeWithClientSecret(String code, String client_id, String secret, boolean needProfile) throws Exception {
        return getClientMigrationRecordByCodeWithClientSecret(code, client_id, secret, needProfile, ConnectBaseUri);
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByCodeWithClientSecretInternal(String code, String client_id, String secret, boolean needProfile) throws Exception {
        return getClientMigrationRecordByCodeWithClientSecret(code, client_id, secret, needProfile, HttpConnectInternalBaseUri);
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByCodeWithClientSecret(String code, String client_id, String secret, boolean needProfile, String baseUri) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
        nameValuePairs.add(new BasicNameValuePair("code", code));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));

        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(baseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (needProfile == true) {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("X-Need-Profile", "true");
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);
        String clientMigrationRecordString = IOUtils.toString(response.getEntity().getContent());
        log.info(clientMigrationRecordString);
        try {
            return TestUtil.parseJson(clientMigrationRecordString, ClientMigrationRecordInfo.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(clientMigrationRecordString);
        }
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByClentCredentials(String pidId, String client_id, String secret, boolean needProfile) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "client_credentials"));
        nameValuePairs.add(new BasicNameValuePair("pidId", pidId));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));

        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(ConnectBaseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (needProfile == true) {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("X-Need-Profile", "true");
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);
        String clientMigrationRecordString = IOUtils.toString(response.getEntity().getContent());
        log.info(clientMigrationRecordString);
        try {
            return TestUtil.parseJson(clientMigrationRecordString, ClientMigrationRecordInfo.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(clientMigrationRecordString);
        }
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByExchange(String accessToken, String client_id, String secret, boolean needProfile) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "exchange"));
        nameValuePairs.add(new BasicNameValuePair("access_token", accessToken));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));

        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(ConnectBaseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (needProfile == true) {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("X-Need-Profile", "true");
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);
        String clientMigrationRecordString = IOUtils.toString(response.getEntity().getContent());
        log.info(clientMigrationRecordString);
        try {
            return TestUtil.parseJson(clientMigrationRecordString, ClientMigrationRecordInfo.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(clientMigrationRecordString);
        }
    }

    public ClientMigrationRecordInfo getClientMigrationRecordByRefreshToken(String refreshToken, String client_id, String secret, boolean needProfile) throws Exception {

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
        nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
        nameValuePairs.add(new BasicNameValuePair("client_id", client_id));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));

        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        HttpPost httpPost = new HttpPost(ConnectBaseUri + "/connect/token");
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        if (needProfile == true) {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("X-Need-Profile", "true");
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }

        HttpResponse response = post(httpPost, httpContext);// client.execute(httpPost, httpContext);
        String clientMigrationRecordString = IOUtils.toString(response.getEntity().getContent());
        log.info(clientMigrationRecordString);
        try {
            return TestUtil.parseJson(clientMigrationRecordString, ClientMigrationRecordInfo.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(clientMigrationRecordString);
        }
    }

    public String getUpidToken(String clientId) throws Exception {
        HttpContext httpContext = new BasicHttpContext();

        CookieStore cookieStore = new BasicCookieStore();
        String oneboxUri = getUpidTokenUri(clientId);
        HttpGet httpGet = new HttpGet(oneboxUri);

        HttpResponse response = get(httpGet, httpContext);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new Exception("Wrong response status for getUpidToken");
        }

        String responseMessage = null;

        if (response.getEntity() != null) {
            responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
        }

        if (responseMessage == null) {
            throw new Exception("Null response returned for getUpidToken");
        }
        return responseMessage;
    }

    public LoginInfo anonymousLogin(String upidToken, String client_id, String client_secret) throws Exception {
        //login anonymously, the pid type is MOBILE_UPID
        String code = getCodeByMobileUpidToken(upidToken, client_id, null);
        AccessToken token = getTokenByCodeWithClientSecret(code, client_id, client_secret);
        List<AccessToken> tokens = new ArrayList<AccessToken>();
        tokens.add(token);
        List<TokenInfo> tokensInfo = getTokensInfo(tokens, client_id);
        Assert.assertNotNull(tokensInfo);
        Assert.assertEquals(1, tokensInfo.size());
        Assert.assertNotNull(tokensInfo.get(0).getPid_id());
        Assert.assertNotNull(tokensInfo.get(0).getUser_id());
        Assert.assertEquals(tokensInfo.get(0).getPid_type(), typeMobileUpid, "Not expected Pid Type");
        LoginInfo li = new LoginInfo();
        li.accessToken = token;
        li.tokenInfo = tokensInfo.get(0);
        li.externalRefValue = upidToken;
        return li;
    }

    public LoginInfo reLogin(LoginInfo li, String client_id, String client_secret) throws Exception {
        if (li.fbUser != null) {
            return facebookLogin(li.fbUser, client_id, client_secret);
        } else if (li.email != null) {
            return mobileoriginLogin(li.email, li.password, client_id, client_secret);
        } else
            return null;
    }

    public LoginInfo facebookLogin(FacebookTestUser fbUser, String client_id, String client_secret) throws Exception {
        String code = getCodeByMobileFacebook(fbUser.getaccess_token(), client_id, null);
        AccessToken token = getTokenByCodeWithClientSecret(code, client_id, client_secret);
        List<AccessToken> tokens = new ArrayList<AccessToken>();
        tokens.add(token);
        List<TokenInfo> tokensInfo = getTokensInfo(tokens, client_id);
        Assert.assertNotNull(tokensInfo);
        Assert.assertEquals(1, tokensInfo.size());
        Assert.assertNotNull(tokensInfo.get(0).getPid_id());
        Assert.assertNotNull(tokensInfo.get(0).getUser_id());
        Assert.assertEquals(tokensInfo.get(0).getPid_type(), typeMobileFacebook, "Not expected Pid Type");
        LoginInfo li = new LoginInfo();
        li.accessToken = token;
        li.tokenInfo = tokensInfo.get(0);
        li.externalRefValue = fbUser.getid();
        li.fbUser = fbUser;
        return li;
    }

    public LoginInfo mobileoriginLogin(String email, String password, String client_id, String client_secret) throws Exception {
        String code = getCodeByMobileOrigin(email, password, client_id);
        AccessToken token = getTokenByCodeWithClientSecretAndRedirectUri(code, client_id, client_secret, "http://localhost");
        List<AccessToken> tokens = new ArrayList<AccessToken>();
        tokens.add(token);
        List<TokenInfo> tokensInfo = getTokensInfo(tokens, client_id);
        Assert.assertNotNull(tokensInfo);
        Assert.assertEquals(tokensInfo.size(), 1);
        LoginInfo li = new LoginInfo();
        li.accessToken = token;
        li.tokenInfo = tokensInfo.get(0);
        li.email = email;
        li.password = password;
        Assert.assertEquals(li.tokenInfo.getPid_type(), typeMobileOrigin);
        return li;
    }

    public LoginInfo mobileoriginLogin(String client_id, String client_secret) throws Exception {
        String email = TestUtil.getRandomEmail();
        String pidUri = NucleusApi.instance().postPid(email, signupPassword);
        String pid = pidUri.substring(6, pidUri.lastIndexOf('/'));
        String personaUri = NucleusApi.instance().postPersona(Long.parseLong(pid), TestUtil.getRandomOriginId());
        String personaId = personaUri.substring(personaUri.lastIndexOf('/') + 1);
        String code = getCodeByMobileOrigin(email, signupPassword, client_id);
        AccessToken token = getTokenByCodeWithClientSecretAndRedirectUri(code, client_id, client_secret, "http://localhost");
        List<AccessToken> tokens = new ArrayList<AccessToken>();
        tokens.add(token);
        List<TokenInfo> tokensInfo = getTokensInfo(tokens, client_id);
        Assert.assertNotNull(tokensInfo);
        Assert.assertEquals(tokensInfo.size(), 1);
        String targetPidId = tokensInfo.get(0).getPid_id();
        Assert.assertEquals(pid, targetPidId);
        LoginInfo li = new LoginInfo();
        li.accessToken = token;
        li.tokenInfo = tokensInfo.get(0);
        li.personaId = personaId;
        li.email = email;
        li.password = signupPassword;
        Assert.assertEquals(li.tokenInfo.getPid_type(), typeMobileOrigin);
        return li;
    }

    public LoginInfo gamecenterLogin(String gamecenterId, String client_id, String client_secret) throws Exception {
        return gamecenterLogin(gamecenterId, client_id, client_secret, null);
    }

    public LoginInfo gamecenterLogin(String gamecenterId, String client_id, String client_secret, String gc_pname) throws Exception {
        String code = "";
        if (gc_pname == null)
            code = getCodeByMobileGameCenterId(gamecenterId, client_id, null);
        else
            code = getCodeByMobileGameCenterIdAndName(gamecenterId, gc_pname, client_id, null);
        AccessToken token = getTokenByCodeWithClientSecret(code, client_id, client_secret);
        List<AccessToken> tokens = new ArrayList<AccessToken>();
        tokens.add(token);
        List<TokenInfo> tokensInfo = getTokensInfo(tokens, client_id);
        Assert.assertNotNull(tokensInfo);
        Assert.assertEquals(1, tokensInfo.size());
        Assert.assertNotNull(tokensInfo.get(0).getPid_id());
        Assert.assertNotNull(tokensInfo.get(0).getUser_id());
        Assert.assertEquals(tokensInfo.get(0).getPid_type(), typeMobileGameCenter, "Not expected Pid Type");
        LoginInfo li = new LoginInfo();
        li.accessToken = token;
        li.tokenInfo = tokensInfo.get(0);
        li.externalRefValue = gamecenterId;
        return li;
    }

    public LoginInfo gamecenterLogin(String gamecenterId, String client_id, String client_secret, String gc_pname, String publicKeyUrl, String signature, String bundleId, String timestamp, String salt) throws Exception {
        String code = getCodeByMobileGameCenterIdAndNameWithValidation(gamecenterId, gc_pname, client_id, null, publicKeyUrl, signature, bundleId, timestamp, salt);
        AccessToken token = getTokenByCodeWithClientSecret(code, client_id, client_secret);
        List<AccessToken> tokens = new ArrayList<AccessToken>();
        tokens.add(token);
        List<TokenInfo> tokensInfo = getTokensInfo(tokens, client_id);
        Assert.assertNotNull(tokensInfo);
        Assert.assertEquals(1, tokensInfo.size());
        Assert.assertNotNull(tokensInfo.get(0).getPid_id());
        Assert.assertNotNull(tokensInfo.get(0).getUser_id());
        Assert.assertEquals(tokensInfo.get(0).getPid_type(), typeMobileGameCenter, "Not expected Pid Type");
        LoginInfo li = new LoginInfo();
        li.accessToken = token;
        li.tokenInfo = tokensInfo.get(0);
        li.externalRefValue = gamecenterId;
        return li;
    }

    public String loginWithRemid(String remid) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();

        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = getCodeUri(client_id);
        HttpGet httpGet = new HttpGet(oneboxUri);

        BasicClientCookie basicClientCookie = new BasicClientCookie("remid", remid);
        basicClientCookie.setPath("/connect");
        basicClientCookie.setDomain(httpGet.getURI().getHost());
        cookieStore.addCookie(basicClientCookie);

        try {
            get(httpGet, httpContext);
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code(redirect successfully)
                return TestUtil.checkRemidInHttpContext(httpContext);
            }
            throw new Exception("login fail");
        } catch (Exception e) {
            //redirect to a not existed website
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return the code
                return TestUtil.checkRemidInHttpContext(httpContext);
            } else {
                List<Cookie> cookies = cookieStore.getCookies();
                String sid = "";
                for (int i = 0; i < cookies.size(); i++) {
                    Cookie cookie = cookies.get(i);
                    if (cookie.getName().equals("JSESSIONID")) {
                        sid = cookie.getValue();
                    }
                }
                log.info(sid + " login with remid: " + remid + " fail");
                throw new Exception(sid + " login with remid: " + remid + " fail");
            }
        }
    }

    public String loginAndCheckRemid(String signupEmail, String signupPassword) throws Exception {
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

        String oneboxUri = getCodeUri(client_id);

        HttpGet httpGet = new HttpGet(oneboxUri);
        get(httpGet, httpContext);

        //post user & pwd to login
        try {
            String currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (!currentUrl.contains("login?execution=")) {
                //String message = IOUtils.toString(((HttpResponse)httpContext.getAttribute("http.response")).getEntity().getContent());
                throw new Exception(IOUtils.toString(((HttpResponse) httpContext.getAttribute("http.response")).getEntity().getContent()));
            }
            HttpPost httpPost = new HttpPost(currentUrl);
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
            nameValuePairs.add(new BasicNameValuePair("email", signupEmail));
            nameValuePairs.add(new BasicNameValuePair("password", signupPassword));
            nameValuePairs.add(new BasicNameValuePair("_rememberMe", "on"));
            nameValuePairs.add(new BasicNameValuePair("rememberMe", "on"));
            nameValuePairs.add(new BasicNameValuePair("_eventId", "submit"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            client.setRedirectStrategy(new LaxRedirectStrategy());
            client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
            post(httpPost, httpContext);//client.execute(httpPost, httpContext);
            currentUrl = TestUtil.getCurrentUrl(httpContext);
            if (currentUrl.contains("?code=")) {
                //return code if user verified email(redirect successfully)
                return TestUtil.checkRemidInHttpContext(httpContext);
            }
        } catch (Exception e) {
            //redirect to a not existed website
            String url = TestUtil.getCurrentUrl(httpContext);
            if (url.contains("?code=")) {
                return TestUtil.checkRemidInHttpContext(httpContext);
            } else {
                RedirectLocations redirectLocations = ((RedirectLocations) httpContext.getAttribute("http.protocol.redirect-locations"));
                if (redirectLocations != null) {
                    List<URI> uris = redirectLocations.getAll();
                    url = uris.get(uris.size() - 1).toASCIIString();
                    if (url.contains("?code=")) {
                        return TestUtil.checkRemidInHttpContext(httpContext);
                    }
                }
                throw e;
            }
        }
        throw new Exception("login failur");
    }


    public AccessToken getTokenWithClientSecretAndOperationMode(String clientId, String secret, String operationMode) throws Exception {
        HttpPost httpPost = new HttpPost(ConnectBaseUri + "/connect/token");
        if (operationMode != null) httpPost.setHeader("X_QA_REDIS_OPERATION_MODE", operationMode);
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("grant_type", "client_credentials"));
        nameValuePairs.add(new BasicNameValuePair("client_id", clientId));
        nameValuePairs.add(new BasicNameValuePair("client_secret", secret));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = post(httpPost, null);
        String tokenString = IOUtils.toString(response.getEntity().getContent());
        try {
            return TestUtil.parseJson(tokenString, AccessToken.class);
        } catch (UnrecognizedPropertyException e) {
            log.info(e.getMessage());
            throw new Exception(response.getStatusLine().getStatusCode() + " " + tokenString);
        }
    }

    public AccessToken getAccessTokenWithScope(String scope, String signupEmail, String signupPassword) throws Exception {
        String code = getCode(signupEmail, signupPassword, scope);
        AccessToken token = getTokenByCodeWithClientSecret(code);
        TokenInfo info = getTokenInfo(token);
        if (scope != null) Assert.assertEquals(scope, info.getScope());
        return token;
    }

    public int postClientInfo(String clientId, String clientSecret, boolean fakeIP) throws Exception {
        String url = postClientInfoUri();
        HttpPost httpPost = new HttpPost(url);
        if (fakeIP) {
            httpPost.addHeader("X-Forwarded-For", "4.3.2.1");
        }

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
        nameValuePairs.add(new BasicNameValuePair("client_id", clientId));
        nameValuePairs.add(new BasicNameValuePair("client_secret", clientSecret));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        HttpResponse response = post(httpPost, null);
        return response.getStatusLine().getStatusCode();
    }

    public boolean checkEmailAddress(HttpContext httpContext) throws Exception{
        HttpGet httpGet = new HttpGet(TestUtil.BasePortalURI() + "/p/ajax/user/checkEmailExisted?requestorId=portal&email=test%40ea.com");
        HttpResponse httpResponse = get(httpGet, httpContext);
        return httpResponse.getStatusLine().getStatusCode() == 200;
    }

    public boolean checkOriginId(HttpContext httpContext) throws Exception{
        HttpGet httpGet = new HttpGet(TestUtil.BasePortalURI() + "/p/ajax/user/checkOriginId?requestorId=portal&originId=test");
        HttpResponse httpResponse = get(httpGet, httpContext);
        return httpResponse.getStatusLine().getStatusCode() == 200;
    }

    public HttpContext getHttpContext() throws Exception{
        CookieStore cookieStore = new BasicCookieStore();
        HttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        String oneboxUri = getCodeUri(client_id);
        HttpGet httpGet = new HttpGet(oneboxUri);
        get(httpGet, httpContext);
        return httpContext;
    }


}
